package com.xiang.plane.model;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.Log;

import com.xiang.plane.util.BZCarve;
import com.xiang.plane.util.Calculate;
import com.xiang.plane.util.ImageUtil;
import com.xiang.plane.util.PVector;
import com.xiang.plane.util.TypeConst;
import com.xiang.plane.view.GameView;

import java.util.List;

/**
 * Create by Xiang Liyou on 2017/8/4
 *
 * @DESCRIPTION 子弹类
 */
public class Bullet {

    private static final String TAG = "Bullet";
    public int bulletX, bulletY;
    public final int width, height;
    //子弹速度
    private int speed = 10;
    //飞机的图片
    private Bitmap bullet;
    //是否是敌机
    private boolean isEnemy = false;
    //子弹类型
    private int bulletType = TypeConst.MY_BULLET_NORMAL_1;
    //是否爆炸状态，是否爆炸结束状态
    public boolean isExplode = false, isExplodeDead = false;
    //爆炸半径,最大爆炸半径
    private int explodeRadius = 0, explodeMaxRadius = 30;
    //目标向量
    private PVector targetV = new PVector(0, 0);
    //默认时垂直向上的
    private PVector initV = new PVector(-1, -1);
    //旋转角度
    private double rotateAngle;
    //贝塞尔曲线的路径点列表
    private List<Point> pointList = null;
    //当前应该取得的路径点索引
    private int pathIndex = 0;

    /**
     * @param bulletX    子弹x坐标
     * @param bulletY    子弹y坐标
     * @param isEnemy    true为是敌机子弹
     * @param bulletType 子弹类型，引用com.xiang.plane.util.TypeConst里的值
     */
    public Bullet(Resources res, int bulletX, int bulletY, boolean isEnemy, int bulletType) {

        this.isEnemy = isEnemy;
        this.bulletType = bulletType;
        if (isEnemy) {
            bullet = ImageUtil.ImageCacahe.get(ImageUtil.ENEMY_BULLET_1);
        } else {
            if (bulletType == TypeConst.MY_BULLET_VECTOR_TRACK) {
                bullet = ImageUtil.ImageCacahe.get(ImageUtil.HERO_TRACK_1);
            } else if (bulletType == TypeConst.MY_BULLET_NORMAL_1) {
                bullet = ImageUtil.ImageCacahe.get(ImageUtil.HERO_BULLET_1_1);
            }

        }

        this.width = bullet.getWidth();
        this.height = bullet.getHeight();

        this.bulletX = bulletX - width / 2;
        this.bulletY = bulletY;

        //设置左向贝塞尔曲线
        if (bulletType == TypeConst.MY_BULLET_BZ_TRACK_1) {
            this.targetV = this.getNestEnemy();
            //设置贝塞尔曲线控制点
            int inflectX = (int) (bulletX + (this.targetV.x - bulletX) / 2 - GameView.screenW / 2);
            int inflectY = (int) (bulletY + (this.targetV.y - bulletY) / 2 - GameView.screenH / 2);
            //创建贝塞尔曲线  传入贝塞尔曲线起点 ,传入贝塞尔曲线控制点,传入贝塞尔曲线终点
            BZCarve crave = new BZCarve(new Point(bulletX, bulletY), new Point(inflectX, inflectY),
                    new Point((int) this.targetV.x, (int) this.targetV.y));
            //初始化贝塞尔曲线的计算，获得路径点
            crave.init();
            //获取路径点列表
            this.pointList = crave.getPointList();
        }
        //设置右向贝塞尔曲线（同上）
        if (this.bulletType == TypeConst.MY_BULLET_BZ_TRACK_2) {
            this.targetV = this.getNestEnemy();
            //设置贝塞尔曲线控制点
            int inflectX = (int) (bulletX + (this.targetV.x - bulletX) / 2 + GameView.screenW / 2);
            int inflectY = (int) (bulletY + (this.targetV.y - bulletY) / 2 - GameView.screenH / 2);
            //创建贝塞尔曲线  传入贝塞尔曲线起点 ,传入贝塞尔曲线控制点,传入贝塞尔曲线终点
            BZCarve crave = new BZCarve(new Point(bulletX, bulletY), new Point(inflectX, inflectY),
                    new Point((int) this.targetV.x, (int) this.targetV.y));
            //初始化贝塞尔曲线的计算，获得路径点
            crave.init();
            //获取路径点列表
            this.pointList = crave.getPointList();
        }

        //加入子弹集合
        GameView.bulletVector.add(this);
    }

    public void drawBullet(Canvas canvas, Paint paint) {
        if (isExplode) {
            drawExplodeType(canvas, paint);
        } else {
            this.drawBulletType(canvas, paint);
        }
    }

    //可以根据子弹类型画不同的击中效果
    private void drawExplodeType(Canvas canvas, Paint paint) {
        //画的方式是空心圆
        paint.setStyle(Paint.Style.STROKE);
        //设置线宽
        paint.setStrokeWidth(4f);
        paint.setColor(Color.RED);
        //画一个圆圈表示爆炸效果
        canvas.drawCircle(bulletX - 10, bulletY - 10, explodeRadius, paint);
        //每一帧让圆的半径增大15
        this.explodeRadius += 10;
        if (this.explodeRadius > this.explodeMaxRadius) {
            this.isExplodeDead = true;
        }
    }


    //根据子弹的类型来渲染内容
    private void drawBulletType(Canvas canvas, Paint paint) {
        /***********旋转子弹方向，跟踪弹，boss的散弹需要旋转*****/
        //旋转的矩阵
        Matrix matrix = new Matrix();
        //旋转
        if (bulletType == TypeConst.MY_BULLET_VECTOR_TRACK ||
                bulletType == TypeConst.MY_BULLET_BZ_TRACK_1 ||
                bulletType == TypeConst.MY_BULLET_BZ_TRACK_2) {
            float rotate = (float) (rotateAngle * 180 / Math.PI);
            Bitmap bitmap = ImageUtil.ImageCacahe.get((int) rotate);
            if (bitmap == null) {
                matrix.postRotate(rotate);
                // 生成新的图片
                bitmap = Bitmap.createBitmap(bullet, 0, 0, width, height, matrix, true);
                ImageUtil.ImageCacahe.put((int) rotate, bitmap);
            }
            canvas.drawBitmap(bitmap, bulletX, bulletY, paint);
        } else {
            canvas.drawBitmap(bullet, bulletX, bulletY, paint);
        }
    }


    //根据子弹的类型更新内容
    private void updateBulletType() {
        switch (this.bulletType) {
            case TypeConst.MY_BULLET_NORMAL_1://我方普通子弹
                //设置初始方向向量
                initV.setVector(0, 0);
                this.bulletY -= speed;
                break;
            case TypeConst.MY_BULLET_LINE:
                this.setSpeed(15);
                break;
            case TypeConst.MY_BULLET_VECTOR_TRACK://跟踪弹
                this.setSpeed(10);
                targetV = getNestEnemy();
                //取得当前的目标向量
                PVector tp = new PVector((targetV.x - this.bulletX), (targetV.y - this.bulletY));
                //让初始向量的模向量加上目标向量的模向量
                initV = initV.normalize().add(tp.normalize());
                break;
            case TypeConst.MY_BULLET_BZ_TRACK_1://左贝塞尔
                Point targetPosL = this.pointList.get(pathIndex++);
                this.bulletX = targetPosL.x;
                this.bulletY = targetPosL.y;
                break;
            case TypeConst.MY_BULLET_BZ_TRACK_2://右贝塞尔
                Point targetPosR = this.pointList.get(pathIndex++);
                this.bulletX = targetPosR.x;
                this.bulletY = targetPosR.y;
                break;

            case TypeConst.ENEMY_BULLET_NORMAL_1://敌方普通子弹
                initV.setVector(0, 0);
                this.bulletY += speed / 2;
                break;
            case TypeConst.ENEMY_BULLET_TRACK_1:
                this.setSpeed(3);
                initV = targetV;
                break;
        }
    }

    //得到离自己最近的敌机的坐标，并返回为向量
    public PVector getNestEnemy() {
        float result = 0;
        int index = -1;
        //循环遍历敌人类，寻找y轴坐标最大的飞机
        for (int i = 0; i < GameView.enemyVector.size(); i++) {
            float yPos = GameView.enemyVector.get(i).y;
            if (yPos > result) {
                result = yPos;
                index = i;
            }
        }
        //如果屏幕上没有飞机，就让子弹垂直往上射
        if (index == -1) return new PVector(this.bulletX + GameView.player.getPlaneWidthHalf(), -1);
        //如果有最近的敌机，返回最近敌机的中间偏下的坐标
        Enemy nestEnemy = GameView.enemyVector.get(index);
        return new PVector(nestEnemy.x + nestEnemy.width / 2, nestEnemy.y + nestEnemy.height);
    }

    private void checkDead() {
        boolean outHeight = this.bulletY > GameView.screenH || this.bulletY < 0;
        boolean outWeight = this.bulletX > GameView.screenW || this.bulletX < 0;
        //在窗体外面
        if (outHeight || outWeight || isExplodeDead) {
            this.destroy();
        }
    }

    //销毁自己，释放资源
    private synchronized void destroy() {
        //从列表中移除，使在程序中没有此对象的引用
        GameView.bulletVector.remove(this);
        //移除到窗体外面
        this.bulletY = 5000;
        this.bulletX = 6000;
    }

    /**
     * 更新子弹的状态
     */
    public void logic() {
        this.checkDead();
        this.updateBulletType();
        this.checkEnemyCollision();
        if (this.bulletType == TypeConst.MY_BULLET_BZ_TRACK_1 ||
                this.bulletType == TypeConst.MY_BULLET_BZ_TRACK_2) return;

        //将x,y坐标，分别加上初始方向模向量的x,y分量*速度值
        this.bulletX = (int) (this.bulletX + initV.x * speed);
        this.bulletY = (int) (this.bulletY + initV.y * speed);

        //计算子弹旋转的角度
        //区分是左偏于垂直线还是右偏于垂直线
        if (initV.x < 0) {//左
            //求initV向量与垂直向量之间的夹角
            this.rotateAngle = -new PVector(0, -1).checkVectorAngle(initV);
        } else {//右
            this.rotateAngle = new PVector(0, -1).checkVectorAngle(initV);
        }

    }

    //遍历检测与敌机的碰撞
    private void checkEnemyCollision() {
        //如果这颗子弹是敌机打出来的，那么不进行与敌机的碰撞检测
        if (this.isEnemy) {
            return;
        }
        //检测这颗子弹与一辆敌机是否碰撞
        for (int i = 0; i < GameView.enemyVector.size(); i++) {
            boolean result = this.judgeEnemyCollision(GameView.enemyVector.get(i));
            //如果有碰撞则跳出循环
            if (result) break;
        }
        //检测这颗子弹与Boss是否碰撞
        for (int i = 0; i < GameView.bossVector.size(); i++) {
            boolean result = judgeBossCollision(GameView.bossVector.get(i));
            //如果有碰撞则跳出循环
            if (result) break;
        }
    }

    //判断这颗子弹与某一敌机是否碰撞
    private boolean judgeEnemyCollision(Enemy enemy) {
        if (Calculate.isRectCollision(this.bulletX, this.bulletY, this.width, this.height,
                enemy.x, enemy.y, enemy.width, enemy.height)) {
            //如果碰撞的话就销毁自己和敌机
            this.isExplode = true;
            enemy.beHit();
            return true;
        }
        return false;
    }
    //判断这颗子弹与某一敌机是否碰撞
    private boolean judgeBossCollision(Boss boss) {
        if (Calculate.isRectCollision(this.bulletX, this.bulletY, this.width, this.height,
                boss.x, boss.y, boss.width, boss.height)) {
            //如果碰撞的话就销毁自己和敌机
            this.isExplode = true;
            boss.beHit();
            return true;
        }
        return false;
    }

    public void setTargetV(PVector targetV) {
        this.targetV = targetV;
    }

    public void setInitV(PVector initV) {
        this.initV = initV;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }
}
